<template>
  <div class="background-container">
    <!-- 两张并排（通常用于两个竖屏图） -->
    <div v-if="showTwoImg" class="background-vertical-pair" :style="{ opacity: pairOpacity }">
      <img
          v-if="imgCache&&imgCache[showImg[0]]?.src||''"
          :src="imgCache&&imgCache[showImg[0]]?.src||''"
          class="vertical-img-left"
      />
      <img
          v-if="imgCache&&imgCache[showImg[1]]?.src||''"
          :src="imgCache&&imgCache[showImg[1]]?.src||''"
          class="vertical-img-right"
      />
    </div>

    <!-- 单张（横屏 或 竖屏 单张） -->
    <div v-else class="background-single" :style="{ opacity: singleOpacity }">
      <img
          v-if="imgCache&&imgCache[showImg[0]]?.src||''"
          :src="imgCache&&imgCache[showImg[0]]?.src||''"
          class="single-img"
      />
    </div>
  </div>

  <!-- 调试入口 -->
</template>

<script setup lang="ts">
import {ref, onMounted} from "vue";
import axiosInstance from "@utils/axiosInstance.js";
import {globalConst} from "@constants/globalConst.js";
import ResponseResult from "@models/ReturnResult.js";
import '@assets/css/style.css'

/** ---- 状态 & 配置 ---- */

interface ImgData {
  url: string;
  src: string; // base64 or url
  isVertical: boolean;
  getTime: number;
  key?: string;
  opacity?: number;
}

const imgCache = ref<ImgData[]>([]);
const showTwoImg = ref(false);
const showImg = ref<number[]>([]); // 当前正在显示的索引（1 或 2 个）
const nextShowImg = ref<number[]>([]); // 预留（暂未使用）
const oldShowImg = ref<number[]>([]); // 上一组（备用）
const singleOpacity = ref(1);
const pairOpacity = ref(1);
const isTransitioning = ref(false); // 是否正在过渡

const localStorageKey = "background_img_cache";
const AUTO_INTERVAL_MS = 60 * 1000;
let autoTimer: number | null = null;

/** ---- 工具函数 ---- */

function shuffleIndices(): number[] {
  const arr = imgCache.value.map((_, i) => i);
  // Fisher-Yates 洗牌算法
  for (let i = arr.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [arr[i], arr[j]] = [arr[j], arr[i]];
  }
  return arr;
}

async function urlToBase64(url: string): Promise<string> {
  if (!url) return url;
  if (url.startsWith("data:image")) return url;
  try {
    const res = await axiosInstance.get(url, {responseType: "blob"});
    return await new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onloadend = () => resolve(reader.result as string);
      reader.onerror = () => reject(new Error("FileReader error"));
      reader.readAsDataURL(res.data);
    });
  } catch (e) {
    console.error("urlToBase64 error:", url, e);
    return url;
  }
}

function loadCacheFromStorage(): ImgData[] | null {
  const s = localStorage.getItem(localStorageKey);
  if (!s) return null;
  try {
    return JSON.parse(s) as ImgData[];
  } catch {
    return null;
  }
}

function saveCacheToStorage() {
  try {
    localStorage.setItem(localStorageKey, JSON.stringify(imgCache.value));
  } catch (e) {
    console.warn("save cache failed", e);
  }
}

/** 按窗口高度缩放后判断：缩放后宽度是否 < 窗口宽度*0.8 -> 若小于则显示两张 */
function calcShowTwoByScaledWidth(naturalW: number, naturalH: number) {
  const scale = window.innerHeight / naturalH; // scale to fit height
  const scaledWidth = naturalW * scale;
  return scaledWidth < window.innerWidth * 0.8;
}

/** 预加载 image 获取 naturalW/naturalH ，并返回 src (dataURL 或 url) */
function preloadOne(src: string): Promise<{ src: string; naturalW: number; naturalH: number }> {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => resolve({src: img.src, naturalW: img.naturalWidth, naturalH: img.naturalHeight});
    img.onerror = (e) => reject(e);
    img.src = src;
  });
}

/* ---- 初始化缓存 ---- */
async function initCache() {
  const parsed = loadCacheFromStorage();
  if (parsed && parsed.length > 0) {
    const first = parsed[0];
    // 如果第一项过期则清空并重新拉取
    if (!first || Date.now() - first.getTime > 24 * 60 * 60 * 1000) {
      localStorage.removeItem(localStorageKey);
      imgCache.value = [];
      await initCache();
      return;
    } else {
      imgCache.value = parsed;
      return;
    }
  }

  // 请求后端文件列表
  try {
    const res = await axiosInstance.get(`${globalConst.baseUrl}getImgList`);
    const result = ResponseResult.fromApiResponse<string>(res.data);
    if (result.isSuccess()) {
      const now = Date.now();
      imgCache.value = result.returnResults.map((raw) => {
        const url = raw.startsWith("data:image") ? raw : `${globalConst.staticResourceUrl}img/${raw}`;
        return {
          url,
          src: "", // 延迟转换
          isVertical: false,
          getTime: now,
          key: `${now}-${Math.random().toString(36).slice(2, 9)}`,
        } as ImgData;
      });
      saveCacheToStorage();
    }
  } catch (e) {
    console.error("fetch img list failed", e);
  }
}

/* ---- 切换到下一组图片 ---- */
async function nextImage() {
  // 防止重复过渡
  if (isTransitioning.value) return;
  isTransitioning.value = true;

  // ensure cache
  if (imgCache.value.length === 0) {
    await initCache();
    if (imgCache.value.length === 0) {
      isTransitioning.value = false;
      return;
    }
  }

  // 先淡出当前图片
  if (showImg.value.length > 0) {
    if (showTwoImg.value) {
      pairOpacity.value = 0;
    } else {
      singleOpacity.value = 0;
    }

    // 等待淡出完成
    await new Promise(resolve => setTimeout(resolve, 1000));
  }

  const indices = shuffleIndices();
  let firstIdx = -1;
  for (const idx of indices) {
    if (!showImg.value.includes(idx)) {
      firstIdx = idx;
      break;
    }
  }
  if (firstIdx < 0) {
    firstIdx = indices[0];
  }

  const firstItem = imgCache.value[firstIdx];
  if (!firstItem.src || Date.now() - firstItem.getTime > 24 * 60 * 60 * 1000) {
    const b = await urlToBase64(firstItem.url);
    firstItem.src = b;
    firstItem.getTime = Date.now();
    imgCache.value[firstIdx] = {...firstItem};
    saveCacheToStorage();
  }

  let loadedFirst;
  try {
    loadedFirst = await preloadOne(firstItem.src);
  } catch (e) {
    console.warn("preload first failed, fallback", e);
    loadedFirst = {src: firstItem.src, naturalW: 1, naturalH: 1};
  }

  const isVert1 = loadedFirst.naturalH > loadedFirst.naturalW;
  imgCache.value[firstIdx].isVertical = isVert1;
  saveCacheToStorage();

  const wantTwo = isVert1 && calcShowTwoByScaledWidth(loadedFirst.naturalW, loadedFirst.naturalH);

  if (wantTwo) {
    let secondIdx: number | null = null;
    for (const idx of indices) {
      if (idx === firstIdx) continue;
      if (showImg.value.includes(idx)) continue;

      const cand = imgCache.value[idx];
      if (!cand.src || Date.now() - cand.getTime > 24 * 60 * 60 * 1000) {
        const b = await urlToBase64(cand.url);
        cand.src = b;
        cand.getTime = Date.now();
        imgCache.value[idx] = {...cand};
        saveCacheToStorage();
      }

      try {
        const loadedCand = await preloadOne(cand.src);
        if (loadedCand.naturalH > loadedCand.naturalW) {
          imgCache.value[idx].isVertical = true;
          saveCacheToStorage();
          secondIdx = idx;
          break;
        } else {
          imgCache.value[idx].isVertical = false;
          saveCacheToStorage();
        }
      } catch {
      }
    }

    if (secondIdx === null) {
      // 没找到合适第二张竖屏 --> 检查缓存中竖屏数量
      const verticalCount = imgCache.value.reduce((acc, it) => acc + (it.isVertical ? 1 : 0), 0);
      if (verticalCount <= 1) {
        // 只有这张竖屏，按你的要求：删除该张并递归加载下一张
        imgCache.value.splice(firstIdx, 1);
        saveCacheToStorage();
        // 递归尝试加载下一张（注意防止无限递归，已删除一项，数组长度变动）
        if (imgCache.value.length > 0) {
          await nextImage();
        } else {
          // 若删除后为空，降级显示 nothing
          showTwoImg.value = false;
          showImg.value = [];
        }
        isTransitioning.value = false;
        return;
      } else {
        // 找不到第二张则退化为单图显示
        showTwoImg.value = false;
        showImg.value = [firstIdx];
        singleOpacity.value = 0;
        requestAnimationFrame(() => (singleOpacity.value = 1));
        setTimeout(() => {
          isTransitioning.value = false;
        }, 1000);
        return;
      }
    } else {
      // 找到 secondIdx：显示两张并排
      showTwoImg.value = true;
      showImg.value = [firstIdx, secondIdx];
      pairOpacity.value = 0;
      requestAnimationFrame(() => (pairOpacity.value = 1));
      setTimeout(() => {
        isTransitioning.value = false;
      }, 1000);
      return;
    }
  }

  // 单图显示（横屏或不满足两张）
  showTwoImg.value = false;
  showImg.value = [firstIdx];
  singleOpacity.value = 0;
  requestAnimationFrame(() => (singleOpacity.value = 1));
  setTimeout(() => {
    isTransitioning.value = false;
  }, 1000);
}

/* ---- 启动 ---- */
onMounted(async () => {
  await initCache();
  await nextImage();
  // 自动轮播（60s）
  if (autoTimer)
    window.clearInterval(autoTimer);
  autoTimer = window.setInterval(() => {
    nextImage().catch((e) => console.error(e));
  }, AUTO_INTERVAL_MS);
});
</script>

<style scoped>
/* ==============================
   二次元红紫主题背景样式 - 基于角色官方立绘配色
   ============================== */
.background-container {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  z-index: -1;
  background: linear-gradient(
      135deg,
      rgba(255, 42, 109, 0.15),
      rgba(211, 54, 255, 0.1),
      rgba(26, 26, 26, 0.3)
  );
  backdrop-filter: blur(8px);
  animation: subtleFloat 12s ease-in-out infinite alternate;
}

/* 单张图片展示（横屏或主背景） */
.background-single {
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  transition: opacity 1.5s cubic-bezier(0.4, 0, 0.2, 1);
}

.single-img {
  width: 100vw;
  height: auto;
  object-fit: contain;
  object-position: top center;
  filter: brightness(0.9) contrast(1.1) saturate(1.15);
  border-radius: 12px;
  transition: transform 1s ease, opacity 1s ease, filter 0.5s ease;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
}

.single-img:hover {
  transform: scale(1.01);
  filter: brightness(0.95) contrast(1.15) saturate(1.2);
}

/* 两张竖图并排 */
.background-vertical-pair {
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  transition: opacity 1.5s cubic-bezier(0.4, 0, 0.2, 1);
  gap: 8px;
  padding: 0 8px;
}

.vertical-img-left,
.vertical-img-right {
  width: calc(50vw - 12px);
  height: 100vh;
  object-fit: cover;
  object-position: top center;
  filter: brightness(0.88) contrast(1.08) saturate(1.12);
  transition: transform 1s ease, opacity 1s ease, filter 0.5s ease;
  border-radius: 8px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
}

.vertical-img-left:hover,
.vertical-img-right:hover {
  transform: scale(1.02);
  filter: brightness(0.92) contrast(1.12) saturate(1.18);
}

/* 切换按钮 - 二次元红紫主题 */
button {
  position: fixed;
  bottom: 40px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9999;
  padding: 12px 24px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  border: 2px solid var(--primary-red);
  border-radius: 12px;
  background: linear-gradient(
      135deg,
      var(--primary-red),
      var(--primary-purple)
  );
  box-shadow: var(--shadow-primary), 0 0 20px rgba(255, 42, 109, 0.3);
  cursor: pointer;
  transition: all 0.3s ease;
  backdrop-filter: blur(8px);
  position: relative;
  overflow: hidden;
}

button::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  transition: left 0.5s ease;
}

button:hover {
  transform: translateX(-50%) translateY(-2px);
  box-shadow: var(--shadow-glow), 0 0 30px rgba(255, 42, 109, 0.5);
  border-color: var(--primary-red-light);
}

button:hover::before {
  left: 100%;
}

button:focus,
button:focus-visible {
  outline: 2px solid var(--accent-blue);
  outline-offset: 2px;
}

/* 浮动动画让背景略微"呼吸" */
@keyframes subtleFloat {
  0%, 100% {
    transform: translateY(0px);
  }
  50% {
    transform: translateY(-8px);
  }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .background-vertical-pair {
    gap: 4px;
    padding: 0 4px;
  }

  .vertical-img-left,
  .vertical-img-right {
    width: calc(50vw - 8px);
    border-radius: 6px;
  }

  button {
    bottom: 20px;
    padding: 10px 20px;
    font-size: 13px;
  }
}

@media (max-width: 480px) {
  .background-vertical-pair {
    flex-direction: column;
    gap: 8px;
    padding: 8px;
  }

  .vertical-img-left,
  .vertical-img-right {
    width: 100vw;
    height: 50vh;
    border-radius: 8px;
  }

  button {
    bottom: 15px;
    padding: 8px 16px;
    font-size: 12px;
  }
}

</style>
